package main

import (
	"crypto/md5"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/wtf/mahjong/model"
	"github.com/wtf/mahjong/utils"
)

type Gem struct {
	OpenId string `json:"uniqueid"`
	Act    string `json:"act"`
	Gem    int    `json:"gem"`
	Time   int    `json:"time"`
	Sign   string `json:"sign"`
}

type Prop2gem struct {
	OpenId string `json:"uniqueid"`
	Num    int    `json:"num"`
	Time   int    `json:"time"`
	Sign   string `json:"sign"`
}

type Videos struct {
	OpenId string `json:"uniqueid"`
	Act    string `json:"act"`
	Time   int    `json:"time"`
	Sign   string `json:"sign"`
}

type VideoAppData struct {
	Types   int    `json:"type"`
	Channel string `json:"channel"`
}

func gemNew(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "gemNew:没有收到数据")
	if err != nil {
		return
	}

	var gemD Gem
	err1 := json.Unmarshal(body, &gemD)
	utils.CheckErr(write, err1, 101, "gemNew:无法解析json数据")
	if err1 != nil {
		return
	}
	// utils.Info("repeatCheck: gem=", gemD.OpenId, gemD.Act)
	// 解密验证
	w := md5.New()
	io.WriteString(w, gemD.OpenId+gemD.Act+strconv.Itoa(gemD.Gem)+strconv.Itoa(gemD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != gemD.Sign {
		utils.Info(gemD, newSign)
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "gemNew:密钥认证失败")
		return
	}

	// 获取用户信息
	userInfo, err3 := model.UserByUniqueId(gemD.OpenId)
	utils.CheckErr(write, err3, 103, "gemNew:获取用户信息失败")
	if err3 != nil {
		return
	}

	if gemD.Gem < 0 || gemD.Gem >= 1000000 {
		utils.CheckErr(write, errors.New("钻石数量错误"), 1088, "gemNew:钻石数量错误")
		return
	}

	// 更新数据库数量
	err77 := userInfo.Update("gem", strconv.Itoa(gemD.Gem))
	utils.CheckErr(write, err77, 1077, "gemNew:更新钻石失败")
	if err77 != nil {
		return
	}

	switch gemD.Act {
	case "back":
		if err8 := userInfo.Update("back", strconv.Itoa(userInfo.Back+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gemNew:back统计失败")
			return
		}
		break
	case "search":
		if err8 := userInfo.Update("search", strconv.Itoa(userInfo.Search+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gemNew:search统计失败")
			return
		}
		break
	case "bomb":
		if err8 := userInfo.Update("bomb", strconv.Itoa(userInfo.Bomb+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gemNew:bomb统计失败")
			return
		}
		break
	case "ext":
		if err8 := userInfo.Update("ext", strconv.Itoa(userInfo.Ext+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gemNew:ext统计失败")
			return
		}
		break
	case "collect":
		if userInfo.Collect == 1 {
			utils.Info(gemD)
			utils.CheckErr(write, errors.New("已经收藏"), 106, "gemNew:已经收藏")
			return
		}
		if err7 := userInfo.Update("collect", strconv.Itoa(1)); err7 != nil {
			utils.CheckErr(write, err7, 107, "gemNew:更新collect失败")
			return
		}
		break
	default:
		utils.CheckErr(write, errors.New("操作无法识别"), 104, "gemNew:操作无法识别")
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func videos(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "videos:没有收到数据")
	if err != nil {
		return
	}

	var videoD Videos
	err1 := json.Unmarshal(body, &videoD)
	utils.CheckErr(write, err1, 101, "videos:无法解析json数据")
	if err1 != nil {
		return
	}
	// utils.Info("repeatCheck: videos=", videoD.OpenId, videoD.Act)
	// 解密验证
	w := md5.New()
	io.WriteString(w, videoD.OpenId+videoD.Act+strconv.Itoa(videoD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != videoD.Sign {
		utils.Info(videoD, newSign)
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "videos:密钥认证失败")
		return
	}

	// 获取用户信息
	userInfo, err3 := model.UserByUniqueId(videoD.OpenId)
	utils.CheckErr(write, err3, 103, "gem:获取用户信息失败")
	if err3 != nil {
		return
	}

	switch videoD.Act {
	case "back":
		if err4 := userInfo.Update("back", strconv.Itoa(userInfo.Back+1)); err4 != nil {
			utils.CheckErr(write, err4, 104, "videos:back统计失败")
			return
		}
		break
	case "search":
		if err4 := userInfo.Update("search", strconv.Itoa(userInfo.Search+1)); err4 != nil {
			utils.CheckErr(write, err4, 104, "videos:search统计失败")
			return
		}
		break
	case "bomb":
		if err4 := userInfo.Update("bomb", strconv.Itoa(userInfo.Bomb+1)); err4 != nil {
			utils.CheckErr(write, err4, 104, "videos:bomb统计失败")
			return
		}
		break
	case "ext":
		if err4 := userInfo.Update("ext", strconv.Itoa(userInfo.Ext+1)); err4 != nil {
			utils.CheckErr(write, err4, 104, "videos:ext统计失败")
			return
		}
		break
	default:
		utils.CheckErr(write, errors.New("操作无法识别"), 106, "videos:操作无法识别")
		return
	}

	if err5 := userInfo.Update("	video_times", strconv.Itoa(userInfo.VideoTimes+1)); err5 != nil {
		utils.CheckErr(write, err5, 105, "videos:video统计失败")
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func gemAct(openId string, act int, num int) (gem int, err error) {
	// 查询用户user_id
	userInfo, err := model.UserByUniqueId(openId)
	if err != nil {
		return
	}

	if act == 0 {
		err = errors.New("缺失动作")
		return
	}

	if num <= 0 {
		err = errors.New("数量错误")
		return
	}

	gem = 0

	switch act {
	case 1: // +
		gem = userInfo.Gem + num
		break
	case -1: // -
		if num > userInfo.Gem {
			err = errors.New("钻数量不足")
			return
		}
		gem = userInfo.Gem - num
		break
	}

	// 更新数据库数量
	if err = userInfo.Update("gem", strconv.Itoa(gem)); err != nil {
		return
	}

	// 返回总数量
	return
}

func generalInvite(write http.ResponseWriter, request *http.Request) {
	// utils.Info("generalInvite check")
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "generalInvite:没有收到解密的数据")
	if err != nil {
		return
	}
	friendD := model.GeneralInvite{}
	err1 := json.Unmarshal(body, &friendD)
	utils.CheckErr(write, err1, 101, "generalInvite:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	if friendD.ShareCode == "" || friendD.OpenId == "" {
		utils.CheckErr(write, errors.New("输入参数不能为空"), 102, "generalInvite:输入参数不能为空")
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	// 根据user_shareCode查询宿主userId
	rootUserId, err3 := redis.Int(rc.Do("HGET", utils.Config.PkgName+"-shareCode_list", friendD.ShareCode))
	utils.CheckErr(write, err3, 103, "generalInvite:查询shareCode用户id失败")
	if err3 != nil {
		return
	}

	openId, err4 := model.OpenIdByUserId(rootUserId)
	utils.CheckErr(write, err4, 104, "generalInvite:获取用户信息失败")
	if err4 != nil {
		return
	}

	if openId == friendD.OpenId {
		utils.CheckErr(write, errors.New("自己不能邀请自己"), 105, "generalInvite:自己不能邀请自己")
		return
	}

	// 获取好友用户信息
	friendInfo, err6 := model.UserByUniqueId(friendD.OpenId)
	utils.CheckErr(write, err6, 106, "generalInvite:获取好友用户信息失败")
	if err6 != nil {
		return
	}

	// 判断是否为新玩家
	var (
		now = int(time.Now().Unix())
	)

	if (now - friendInfo.Time) > 2 { // 老用户
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
		}
		returnDa.Returnfunc(write)
		return
	}

	// 将该好友添加至好友列表  供以后使用
	err7 := addFriend(openId, friendD.OpenId)
	utils.CheckErr(write, err7, 107, "generalInvite:添加好友失败")
	if err7 != nil {
		return
	}

	// 邀请的是新玩家 获得200钻石
	// 获取好友用户信息
	userInfo, err8 := model.UserByUniqueId(openId)
	utils.CheckErr(write, err8, 108, "generalInvite:获取用户信息失败")
	if err8 != nil {
		return
	}

	err9 := inviteMoney(userInfo, friendInfo)
	utils.CheckErr(write, err9, 109, "generalInvite:邀请好友获得现金失败")
	if err9 != nil {
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func addFriend(openId string, friend string) (err error) {
	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	_, err = rc.Do("sadd", utils.Config.PkgName+"_friend-"+openId, friend)
	return
}

func inviteMoney(userInfo model.User, friendInfo model.User) (err error) {

	var inviteServer = model.NewInviteGemServer()
	var inviteInfo model.InviteGem

	// 判断是否有记录
	inviteInfo, err = inviteServer.GetById(userInfo.UniqueId)
	if err != nil { // 没有记录,添加
		inviteInfo = model.InviteGem{
			OpenId: userInfo.UniqueId,
		}
		err = inviteServer.Create(&inviteInfo)
		if err != nil { // invitePower:添加邀请记录失败
			return
		}

		inviteInfo.Invite = strconv.Itoa(friendInfo.Id)
		inviteInfo.IsGet = "0"
		err = inviteServer.UpdateInvite(inviteInfo)
		return
	}

	// 判断是否已经邀请
	inviteArr := strings.Split(inviteInfo.Invite, ",")
	for _, v := range inviteArr {
		if v == strconv.Itoa(friendInfo.Id) {
			return
		}
	}

	// 判断是否超过100人上限.
	isGetArr := strings.Split(inviteInfo.IsGet, ",")
	if len(isGetArr) >= 100 {
		return
	}

	inviteInfo.Invite = inviteInfo.Invite + "," + strconv.Itoa(friendInfo.Id)
	inviteInfo.IsGet = inviteInfo.IsGet + "," + "0"

	err = inviteServer.UpdateInvite(inviteInfo)
	return
}
